import json
import os

from api.Agefans_app import AgeAppApi
import re
from download.program_interface import aria2c_download, m3u8_download, get_download_dir
from util.url_handler import handler_real_download_url, handler_88kan_play_url
from tqdm import tqdm
from api.M88KanTvApi import get_play_list as get_88kan_play_list

PLAY_URL_INFO_PATTERN = re.compile(r'play/(\d+)\?playid=(\d+)_(\d+)')

api = None


def decode_play_page_url(url: str):
    """
    解析网页播放链接
    :param url: 网页播放链接
    """
    info = PLAY_URL_INFO_PATTERN.findall(url)[0]
    return {
        'aid': int(info[0]),
        'ep_index': int(info[2]),
        'play_index': int(info[1])
    }


def get_play_ep_list(aid: int, play_index=None, ep_index=None):
    """
    获取指定ID番剧播放列表集合
    :param aid: 番剧ID
    :param play_index: 播放页号
    :param ep_index: 集号
    :return 动画名称，播放列表
    """
    detail = api.get_detail(aid=aid)['AniInfo']
    name = detail['R动画名称']
    info = detail['R在线播放All']
    if play_index:
        info = info[play_index - 1]
        if ep_index:
            info = [info[ep_index - 1]]
    return name, info


def download_video_handler(download_link: str, download_mode: int, downloadDir: str, fileName: str):
    """
    使用不同的方式下载视频
    :param download_link: 下载链接
    :param download_mode: 下载模式[0:m3u8, 1:http]
    :param downloadDir: 下载存储到的目录
    :param fileName: 文件名
    :return 是否成功
    """
    if os.path.exists(os.path.join(download_link, f"{fileName}.mp4")):
        return True
    if download_mode == 0:
        return m3u8_download(url=download_link, work_dir=downloadDir, filename=fileName)
    else:
        return aria2c_download(url=download_link, work_dir=downloadDir, filename=fileName + '.mp4')


def save_data_to_json(path: str, data):
    """
    将数据保存到本地并格式化
    :param path: 路径
    :param data: 数据
    """
    with open(path, "w", encoding='utf-8') as f:
        f.write(json.dumps(data, indent=4, ensure_ascii=False))


def download_agefans_vide_list(download_dir: str, aid: int, play_index: int, ep_index=None):
    """
    下载视频列表
    :param download_dir: 下载存储到的目录
    :param aid:番剧ID
    :param play_index: 播放标号
    :param ep_index: 集号
    """
    animateName, play_ep_list = get_play_ep_list(aid=aid, play_index=play_index, ep_index=ep_index)
    download_dir = os.path.join(download_dir, animateName)
    success = 0
    failed = 0
    failed_list = []
    if not os.path.exists(download_dir):
        os.makedirs(download_dir)
    with tqdm(total=len(play_ep_list), desc=f"下载{animateName}") as tq:
        for ep in play_ep_list:
            download_link, mode = handler_real_download_url(play_id=ep['PlayId'], vid=ep['PlayVid'], api=api)
            if download_video_handler(
                    download_mode=mode,
                    download_link=download_link,
                    downloadDir=download_dir,
                    fileName=ep['Title']):
                success += 1
            else:
                failed += 1
                failed_list.append(ep['Title'])
            tq.set_postfix({
                "name": ep['Title'],
                "s": success,
                "f": failed
            })
            tq.update(1)
    if failed_list:
        print(f"------------《{animateName}》下载失败列表---------------")
        save_data_to_json(os.path.join(download_dir, f"{animateName}_failed_list.json"), {
            "aid": aid,
            "play_index": play_index,
            "ep_index": ep_index,
            "failed_ep_list": failed_list
        })
        for item in failed_list:
            print(item)
        print("------------------------------------------------------")
        print(f"已下载成功{success}项,失败{failed}项目")
    else:
        print(f"--------------《{animateName}》下载完成----------------")
        print(f"全部下载成功,共计{success}项")
        print("------------------------------------------------------")


def download_88kan_video_list(download_dir: str, playUrl: str, onlyThisEp=True):
    data = get_88kan_play_list(url=playUrl)
    download_dir = os.path.join(download_dir, data['name'])
    play_url_list = []
    if onlyThisEp:
        play_url_list.append(data['url'][data['ep']])
    else:
        play_url_list = data['url']
    failedList = []
    success = 0
    failed = 0
    with tqdm(desc=f"下载《{data['name']}》", total=len(play_url_list)) as tq:
        for i in play_url_list:
            url, mode = handler_88kan_play_url(playUrl=i[1])
            tq.set_postfix({"ep": i[0], "state": "下载中"})
            if download_video_handler(download_link=url, download_mode=mode, downloadDir=download_dir,
                                      fileName=i[0]):
                success += 1
                tq.set_postfix({"ep": i[0], 's': success, 'f': failed, "state": "成功"})
            else:
                failed += 1
                failedList.append(i[0])
                tq.set_postfix({"ep": i[0], 's': success, 'f': failed, "state": "失败"})
            tq.update(1)
    if failedList:
        print(f"------------《{data['name']}》下载失败列表---------------")
        save_data_to_json(os.path.join(download_dir, f"{data['name']}_failed_list.json"), {
            "url": playUrl,
            "failedList": failedList
        })
        for item in failedList:
            print(item)
        print("------------------------------------------------------")
        print(f"已下载成功{success}项,失败{failed}项目")
    else:
        print(f"--------------《{data['name']}》下载完成----------------")
        print(f"全部下载成功,共计{success}项")
        print("------------------------------------------------------")


if __name__ == '__main__':
    play_url = input("播放地址:")
    print("""1. 下载当前集
2. 下载全部
    """)
    number = int(input("输入编号:"))
    if play_url.find('agefans') > -1:
        api = AgeAppApi()
        play = decode_play_page_url(play_url)
        if number == 1:
            download_agefans_vide_list(download_dir=get_download_dir(), aid=play['aid'], play_index=play['play_index'],
                                       ep_index=play['ep_index'])
        if number == 2:
            download_agefans_vide_list(download_dir=get_download_dir(), aid=play['aid'], play_index=play['play_index'])
    elif play_url.find('88kan') > -1:
        download_88kan_video_list(download_dir=get_download_dir(), playUrl=play_url, onlyThisEp=number == 1)
    else:
        print("未知链接：", play_url)
    input("操作结束，回车退出！")
